import { useCallback, useEffect, useState } from "react";
import './index.css'
import { useWorkspace } from "../../../src/app/workspace";
import { NotWallet, Melic } from '../dialog/message'
import { AnchorError } from "@coral-xyz/anchor/dist/cjs/error";
import { PublicKey, SYSVAR_RENT_PUBKEY, SystemProgram } from "@solana/web3.js";
import { ASSOCIATED_PROGRAM_ID, associatedAddress } from "@coral-xyz/anchor/dist/cjs/utils/token";
import { config } from "../../../src/app/utils/config"
import {  SYSVAR_SLOT_HASHES_PUBKEY} from "@solana/web3.js";
import { TOKEN_PROGRAM_ID } from "@coral-xyz/anchor/dist/cjs/utils/token";
import { safeDivide, restoreOriginalValue} from "../../../src/app/utils/bignum";
import BN from "bn.js";
import { NoData } from '../nodata/index'
import { Loading } from '../loading/index'

interface TicketData {
  ticket: string;
}

export const MyBox = () =>{

  const work = useWorkspace();
  const [list, setList] = useState<TicketData[]>([]);
  const [ showError, setShowError ] = useState('')
  const [ showMelic, setShowMelic ] = useState('')
  const [ isload, setIsload ] = useState(false)
  const [ showLoading, setShowLoading ] = useState(false)
  // 成功
  const toggleMelic = (text: string) =>{
    setShowMelic(text)
  }
  // 失败
  const toggleError = (text: string) =>{
    setShowError(text)
    setTimeout(() => {
      setShowError('')
    }, 2000);
  }

  const getData = useCallback(async () => {
    try {
      let filteredResults: TicketData[] = [];
      if (work && work.wallet) {
        const { connection, program, wallet, provider } = work;
        //const umi = createUmi(config.rpc).use(mplTokenMetadata());
        const userString = wallet.publicKey.toString();




          const filters = [{
            memcmp: {
              offset: 8, // owner字段在account数据中的起始位置
              bytes: userString,
            },
          }];

          const stakeInfoAccounts = await program.account.nftBuy.all(filters);
          console.log('stakeInfoAccounts', stakeInfoAccounts);
          setIsload(true)
          //数据返回
          if(stakeInfoAccounts){
            for (const accountInfo of stakeInfoAccounts) {
              const ticketString = accountInfo.publicKey.toBase58();
              console.log('ticketString', ticketString);
              filteredResults.push({
                ticket: ticketString,
              });
            }

          }

        }

        setList(filteredResults);

    } catch (error) {

      if (error instanceof AnchorError) {
        const code = error.error.errorCode.code;
        const number = error.error.errorCode.number;
        const message = error.error.errorMessage;
        //showToastError('捕获到的错误')
        console.error('捕获到的错误: ', code, number, message);
      } else {
        //showToastError('未知错误')
        console.error('未知错误: ', error);
      }
    }
  }, [work]);

  useEffect(() => {
    getData();
  }, [getData]);

  const handle = async (box: TicketData) => {
    setShowLoading(true)
    try {
      if (work && work.wallet) {

          const { connection, program, wallet, provider } = work;
          const mint = new PublicKey(config.token);
          const user = provider.wallet.publicKey;
          let beforeAmount = "0";
          let afterAmount = "0";
          try {

            const pay = await connection.getParsedAccountInfo(mint);

              const tokenData = pay.value.data.parsed.info;

              if(!tokenData.isInitialized){
                console.error('代币未初始化');
              }

              console.log(tokenData);
              const userVault = associatedAddress({
                  mint: mint,
                  owner: user
                });
              if(userVault){
                const findAccountARes = await connection.getTokenAccountBalance(userVault);
                if(findAccountARes){
                  beforeAmount = findAccountARes.value.amount;
                  console.log(beforeAmount);
                }

              }


          } catch (error) {

            console.error('fetch error');
          }


          const ticket = new PublicKey(box.ticket);
          const user_token_account =  associatedAddress({
          mint: mint,
          owner: user
          });

          const fund_pool = PublicKey.findProgramAddressSync([Buffer.from("fund_pool"), mint.toBuffer()], program.programId)[0];//资金池
          const blind_box = PublicKey.findProgramAddressSync([Buffer.from("blind_box"), mint.toBuffer()], program.programId)[0];//token 盲盒


          try {

              const tx = await program.methods
              .openBox()
              .accounts({
                  user: user,//用户
                  ticket: ticket,//购买的支票
                  mint: mint,//初始化的token mint
                  fundPool: fund_pool,//资金池
                  userToken: user_token_account,//用户token地址
                  blindBox: blind_box,//token 盲盒
                  systemProgram: SystemProgram.programId,
                  tokenProgram: TOKEN_PROGRAM_ID,
                  associatedTokenProgram: ASSOCIATED_PROGRAM_ID,
                  rent: SYSVAR_RENT_PUBKEY,
                  slotHashes: SYSVAR_SLOT_HASHES_PUBKEY
              })
              .signers([])
              .rpc();
              console.log("Your transaction signature", tx);
              try {

                const pay = await connection.getParsedAccountInfo(mint);

                  const tokenData = pay.value.data.parsed.info;

                  if(!tokenData.isInitialized){
                    console.error('代币未初始化');
                  }

                  //console.log(tokenData);
                  const userVault = associatedAddress({
                      mint: mint,
                      owner: user
                    });


                    const findAccountARes = await connection.getTokenAccountBalance(userVault);
                    afterAmount = findAccountARes.value.amount;




              } catch (error) {

                console.error('fetch error');
              }

              console.log("beforeAmount",beforeAmount)
              console.log("afterAmount",afterAmount)
              const afterAmountBn = new BN(afterAmount);
              const beforeAmountBn = new BN(beforeAmount);
              const earnAmount = afterAmountBn.sub(beforeAmountBn);
              //console.log(earnAmountString)
              const earnAmounUi = restoreOriginalValue(earnAmount,config.tokenDecimals)
              console.log(earnAmounUi.toString())
              setShowLoading(false)
              toggleMelic(earnAmounUi.toString());

               //showToastSuccess('UnStake Success');
               setList((prevList) => prevList.filter((item) => item.ticket !== box.ticket));
          } catch (error) {
              //toggleError("open fail");
              if (error instanceof AnchorError) {

                  //showToastError("UnStake Fail");
                  const code = error.error.errorCode.code ;
                  const number = error.error.errorCode.number ;
                  const  message = error.error.errorMessage;

                  console.error('捕获到的错误: ', code,number,message);
                  // 在这里处理错误，例如显示错误消息给用户
              } else {
                  // 处理其他类型的错误
                  console.error('未知错误: ', error);
              }
            }

          // Example operation: remove NFT from list


          // Add your specific logic for my NFTs here

        }else{
          const walletBtn:any = document.querySelector('.wallet-adapter-button')
          console.log(walletBtn)
          setShowLoading(false)
          walletBtn.click()
        }
    } catch (error) {
      setShowLoading(false)
      console.error('Failed to extract NFT:', error);
    }
  };

  return (
    <>
      <div className="mybox">
        {
          list.map((box) => (
            <div className="mybox-item" key={box.ticket}>
              <div className="mybox-item-thumb">
                <img className="mybox-item-icon" src="../../assets/lipin.png" alt="" />
              </div>
              <div className="mybox-item-title">#{box.ticket}</div>
              <div onClick={() =>handle(box)} className="mybox-item-btn">Open</div>
            </div>
          ))
        }
      </div>
      {
        showError && <NotWallet text={showError}/>
      }
      {
        showMelic && <Melic
        onCancel={() =>{
          toggleMelic('')
        }}
        text={showMelic}/>
      }
      {
        list.length === 0 && isload && <NoData/>
      }
      {
        showLoading && <Loading/>
      }
    </>

  )
}
